//TODO: guard
//TODO: test if all headers are necesary

#include <boost/preprocessor/control/if.hpp>
//#include <boost/preprocessor/comparison/equal.hpp>
#include <boost/preprocessor/comparison/not_equal.hpp>
//#include <boost/preprocessor/repetition/for.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
//#include <boost/preprocessor/tuple/eat.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/seq/seq.hpp>
#include <boost/preprocessor/seq/reverse.hpp>


#define FOR_EACH_WITH_SEPARATOR_PRED(r, state)  \
	BOOST_PP_NOT_EQUAL(							\
		BOOST_PP_SEQ_SIZE(						\
			BOOST_PP_TUPLE_ELEM(2,0,state)		\
		),										\
		1										\
	)											\
/**/

#define FOR_EACH_WITH_SEPARATOR_OP(r, state)	\
	(											\
		BOOST_PP_SEQ_TAIL(						\
			BOOST_PP_TUPLE_ELEM(2,0,state)		\
		),										\
		BOOST_PP_TUPLE_ELEM(2,1,state)			\
	)
/**/


#define INNER_ELEMENT(r, state) BOOST_PP_TUPLE_ELEM(2,1,state)( BOOST_PP_TUPLE_ELEM(2,0,state) ),

#define LAST_ELEMENT(r, state)  BOOST_PP_TUPLE_ELEM(2,1,state)( BOOST_PP_TUPLE_ELEM(2,0,state) )

#define FOR_EACH_WITH_SEPARATOR( SEQ, ACTION ) \
	BOOST_PP_FOR( (SEQ, ACTION), FOR_EACH_WITH_SEPARATOR_PRED, FOR_EACH_WITH_SEPARATOR_OP, INNER_ELEMENT) LAST_ELEMENT(0, (BOOST_PP_SEQ_REVERSE(SEQ), ACTION) )


